const Clutter = imports.gi.Clutter;
const GLib    = imports.gi.GLib;
const Lang    = imports.lang;
const Mx      = imports.gi.Mx;
const Octopus = imports.gi.Octopus;
const OctopusMx  = imports.gi.OctopusMx;
const Signals = imports.signals;

const AlbumArt = imports.albumArt;

const ALBUM_SIZE = 150;

function BrowsePanel(container) {
	this._init(container);
}

BrowsePanel.prototype = {
	_init: function (container) {
		this.stage = container.get_stage ();
		this.browsePanelStack = new Mx.Stack ({ name: 'browsePanel-background',
		                                        reactive: true });
		container.add_child (this.browsePanelStack);
		this.browsePanelStack.connect('button-release-event', Lang.bind(this, this.onButtonReleaseEvent));

		this.browseScrollView = new Mx.KineticScrollView ({ style_class: 'browsePanel-scrollview',
		                                                    snap_on_page: false });
		this.browsePanelStack.add_child (this.browseScrollView);
		this.browseScrollView.connect ('notify::allocation', Lang.bind(this, function () {
			let padding_top = this.browseLayout.get_padding_top ();
			let padding_bottom = this.browseLayout.get_padding_bottom ();
			let row_spacing = this.browseLayout.row_spacing;
			let target_height = this.browseScrollView.height * 0.75;
			let rows = (target_height - padding_top - padding_bottom) /  (row_spacing + ALBUM_SIZE);
			//rows = rows | 0; //float to int
			rows = rows.toFixed ();
			this.browseLayout.height = padding_top + rows * (row_spacing + ALBUM_SIZE);
			this.reflection.height = this.browseScrollView.height - this.browseLayout.height;
		}));

		//horizontal layout to get horizontal scrolling; scrollview.scroll_policy does not have the same effect
		this.horizontalScrollLayout = new Mx.BoxLayout ({ orientation: Mx.Orientation.HORIZONTAL });
		this.browseScrollView.add_child (this.horizontalScrollLayout);
		this.horizontalScrollLayout.horizontal_adjustment.connect ('notify::value', Lang.bind(this, function () {
			this.browseLayout.adjustment = this.horizontalScrollLayout.horizontal_adjustment.value;
		}));

		this.browseReflectionLayout = new Mx.BoxLayout ({ orientation: Mx.Orientation.VERTICAL });
		this.horizontalScrollLayout.add_child (this.browseReflectionLayout);

/*		this.browseLayout = new Mx.Grid ({ style_class: 'browsePanel-layout',
		                                   orientation: Mx.Orientation.VERTICAL,
		                                   y_align: Clutter.ActorAlign.START,
		                                   //homogenous_rows: true,
		                                   //homogenous_columns: true,
		                                   homogenous_rows: false,
		                                   homogenous_columns: false,
		                                   row_spacing: 5,
		                                   column_spacing: 5 });*/
		this.browseLayout = new OctopusMx.MxGrid ({ style_class: 'browsePanel-layout',
		                                            row_spacing: 5,
		                                            column_spacing: 5,
		                                            visible_width: this.stage.width });
		this.stage.connect ('notify::allocation', Lang.bind(this, function () {
			this.browseLayout.visible_width = this.stage.width;
		}));
		this.browseReflectionLayout.add_child (this.browseLayout);
		this.browseLayout.connect ('notify::allocation', Lang.bind(this, function () {
			this.reflectionEffect.original_height = this.browseLayout.height;
		}));

		this.reflection = new Clutter.Clone ({ source: this.browseLayout });
		this.reflectionEffect = new OctopusMx.MxReflectionEffect ({ opacity: 0.3,
		                                                            original_height: this.browseLayout.height });
		this.reflection.add_effect_with_name ("Reflection", this.reflectionEffect);
		this.browseReflectionLayout.add_child (this.reflection);

		this.deform = new OctopusMx.MxZDeform ({ grid: this.browseLayout });
		this.browseReflectionLayout.add_effect_with_name ("DeformZ", this.deform);

		this.browsePanelSearchStack = new Mx.Stack ({ x_align: Clutter.ActorAlign.START,
		                                              y_align: Clutter.ActorAlign.START,
		                                              visible: false });
		this.browsePanelStack.add_child (this.browsePanelSearchStack);
		this.browsePanelSearchEntry = new Mx.Entry ({ style_class: 'browsePanel-search-entry',
		                                              width: 200,
		                                              height: 40 });
		this.browsePanelSearchStack.add_child (this.browsePanelSearchEntry);

		this.browsePanelSearchCloseButton = new Mx.Button ({ style_class: 'browsePanel-search-close',
		                                                     x_align: Clutter.ActorAlign.END,
		                                                     y_align: Clutter.ActorAlign.START,
		                                                     width: 20,
		                                                     height: 20 });
		this.browsePanelSearchStack.add_child (this.browsePanelSearchCloseButton);
		this.browsePanelSearchCloseButton.connect ('clicked', Lang.bind(this, function () {
			this.browsePanelSearchEntryClose ();
		}));
		this.timelineSearchClose = new Clutter.Timeline ({ duration: 3000 });
		this.timelineSearchClose.connect ('completed', Lang.bind(this, function () {
			if (this.browsePanelSearchStack.visible) this.browsePanelSearchEntryClose ();
		}));

		this.browsePanelOverlay = new Mx.Frame ({ name: 'browsePanel-overlay' });
		this.browsePanelStack.add_child (this.browsePanelOverlay);

		//create model
		this.albumlist = new Octopus.Albumlist ();
	},

	on_albumlistmodel_add: function (/*IMedialibQuery*/albumlist_model, /*IMedialibInfo*/album_model) {
		let entry = new Album (this.browseLayout, album_model);
		entry.albumArt.connect('album-art-loaded', Lang.bind(this, function (album) {
			this.loadedCounter++;
			if (this.loadedCounter == this.albumlist.get_size ()) {
				this.emit ('load-finished');
			}
		}));
		entry.albumArt.loadAlbumArt (album_model.picture_front);

		entry.connect('album-enter-event', Lang.bind(this, function (album) {
			this.emit ('show-message-bar-text', album_model.get_artist_performer ()
			                                    + " - "
			                                    + album_model.get_album_partofset ());
		}));
		entry.connect('album-leave-event', Lang.bind(this, function (album) {
			this.emit ('show-message-bar-text', "");
		}));
		entry.connect('button-release-double-click', Lang.bind(this, function (album) {
			this.emit ('tracklist-panel-show', album_model);
		}));
	},

	onKeyPressEvent: function (/*Clutter.KeyEvent*/ event) {
		if (event.get_key_symbol () == Clutter.KEY_Home) { //Home
			this.browseScrollView.horizontal_adjustment.value = 0;
		}
		if (event.get_key_symbol () == Clutter.KEY_End) { //End
			let album_x = this.browseLayout.get_child_at_index (this.browseLayout.get_n_children ()-1).x;
			this.browseScrollView.horizontal_adjustment.value = album_x - (this.stage.width/2);
			//this.browseScrollView.horizontal_adjustment.value = this.browseScrollView.horizontal_adjustment.upper;
		}
		if (event.get_key_symbol () == Clutter.KEY_Page_Up) { //Page_Up
			this.browseScrollView.horizontal_adjustment.value =
			    this.browseScrollView.horizontal_adjustment.value
			  - (this.stage.width - ALBUM_SIZE);
			//  - this.browseScrollView.horizontal_adjustment.page_increment;
		}
		if (event.get_key_symbol () == Clutter.KEY_Page_Down) { //Page_Down
			this.browseScrollView.horizontal_adjustment.value =
			    this.browseScrollView.horizontal_adjustment.value
			  + (this.stage.width - ALBUM_SIZE);
			//  + this.browseScrollView.horizontal_adjustment.page_increment;
		}
		if (   event.get_key_symbol () == Clutter.KEY_Up
		    || event.get_key_symbol () == Clutter.KEY_Left) { //Up, Left
			this.browseScrollView.horizontal_adjustment.value =
			    this.browseScrollView.horizontal_adjustment.value
			    - ALBUM_SIZE;
			//  - this.browseScrollView.horizontal_adjustment.step_increment;
		}
		if (   event.get_key_symbol () == Clutter.KEY_Down
		    || event.get_key_symbol () == Clutter.KEY_Right) { //Down, Right
			this.browseScrollView.horizontal_adjustment.value =
			    this.browseScrollView.horizontal_adjustment.value
			    + ALBUM_SIZE;
			//  + this.browseScrollView.horizontal_adjustment.step_increment;
		}

		if (GLib.unichar_isprint (event.get_key_unicode ())) {
			this.notifyTextSignalId =
			this.browsePanelSearchEntry.connect ('notify::text', Lang.bind(this, function (/*Mx.Entry*/ entry) {
				//search_string_position returns -1 for no match
				let searchTextScrollPosition = this.albumlist.search_string_position (this.browsePanelSearchEntry.text);
				if (searchTextScrollPosition >= 0) {
					let album_x = this.browseLayout.get_child_at_index (searchTextScrollPosition).x;
					this.browseScrollView.horizontal_adjustment.value = album_x - 100;
				}
			}));
			this.browsePanelSearchStack.visible = true;
			this.browsePanelSearchEntry.set_text (event.get_key_unicode ());
			this.browsePanelSearchEntry.grab_key_focus ();
			this.timelineSearchClose.start ();
		}
	},

	onButtonReleaseEvent: function (actor, event, user_data) {
		this.emit ('grab-key-focus');
		return true; //stop
	},

	browsePanelSearchEntryClose: function () {
		this.browsePanelSearchEntry.disconnect (this.notifyTextSignalId);
		this.browsePanelSearchEntry.text = "";
		this.browsePanelSearchStack.visible = false;
	},

	load: function () {
		this.loadedCounter = 0;
		this.browseLayout.remove_all_children ();
		this.loadedSignalId =
		this.albumlist.connect ('loaded', Lang.bind(this, function () {
			this.albumlist.disconnect (this.loadedSignalId);
			this.addSignalId =
			this.albumlist.connect ('add', Lang.bind (this, this.on_albumlistmodel_add));
			this.addFinishedSignalId =
			this.albumlist.connect ('add-finished', Lang.bind(this, function () {
				this.albumlist.disconnect (this.addSignalId);
				this.albumlist.disconnect (this.addFinishedSignalId);
				if (this.browseLayout.get_n_children () == 0) {
					print ("EMPTY ALBUMLIST");
					this.noResultText = new Mx.Label ({ style_class: 'noResultText-label' });
					this.noResultText.text = "no result";
					this.browseLayout.add_child (this.noResultText);
					this.emit ('load-finished');
				}
			}));
			this.albumlist.request_data ();
		}));
		this.albumlist.load ();
	}
};

Signals.addSignalMethods(BrowsePanel.prototype);

function Album(container, /*IMedialibInfo*/album_model) {
	this._init(container, /*IMedialibInfo*/album_model);
}

Album.prototype = {
	_init: function (container, /*IMedialibInfo*/album_model) {
		//requires: album_model of type Album
		this.albumStack = new Mx.Stack ({ name: "album-background" });
		container.add_child (this.albumStack);
		this.albumArt = new AlbumArt.AlbumArt (this.albumStack,
		                                       ALBUM_SIZE);
		this.albumArt.defaultAlbumArtArtist.text = album_model.get_artist_performer ();
		this.albumArt.defaultAlbumArtAlbum.text  = album_model.album;

		this.albumOverlay = new Mx.Frame ({ name: 'album-overlay',
		                                    reactive: true });
		this.albumStack.add_child (this.albumOverlay);
		this.albumOverlay.connect ('enter-event', Lang.bind(this, function () {
			this.emit ('album-enter-event');
		}));
		this.albumOverlay.connect ('leave-event', Lang.bind(this, function () {
			this.emit ('album-leave-event');
		}));
		this.albumOverlay.connect('button-release-event', Lang.bind(this, this.onButtonReleaseEvent));
	},

	onButtonReleaseEvent: function (actor, event, user_data) {
		if ((event.get_button () == 1) && (event.get_click_count () == 1)) { //left mouse button
		}
		if ((event.get_button () == 1) && (event.get_click_count () == 2)) { //double click
			this.emit ('button-release-double-click');
			return true; //stop
		}
		if ((event.get_button () == 3) && (event.get_click_count () == 1)) { //right mouse button
		}
		return false; //propagate
	}
};

Signals.addSignalMethods(Album.prototype);
